<template>
  <div class="dynamic_form_item">
    <a-form-item :name="props.question.key">
      <template v-slot:label>
        <label for="">{{ props.question.label }}</label>
        <a-tooltip v-if="props.question.state.tipText" :key="props.question.label" :title="props.question.state.tipText">
          <i class="iconfont" :style="{ marginLeft: '8px' }" :class="props.question.state.tipIconClassName"></i>
        </a-tooltip>
      </template>
      <template v-if="props.config?.isView">
        <span v-if="props.question.state.labelKey">{{ showKeyName(props.dataForm, props.question.state.labelKey) }}</span>
        <span v-else :style="{ color: props.question.state?.color?.[props.question.value] }">{{ staticView }}</span>
      </template>
      <template v-else>
        <template v-if="props.question.type === 'search'">
          <a-select
            v-model:value="props.question.value"
            showSearch
            :disabled="props.question.disabled"
            :getPopupContainer="hangBody"
            :allowClear="props.question.state.allowClear === false ? false : true"
            :placeholder="props.question.placeholder || '请输入'"
            style="width: 100%"
            :mode="props.question.state.mode"
            :placement="props.question.state?.placement || 'bottomLeft'"
            :filter-option="props.question.state?.filterSearch ? filterOption : false"
            :not-found-content="state.fetching ? undefined : null"
            :options="state.data"
            :fieldNames="props.question.state.asChildren ? props.question.state.asChildren : fieldNames"
            :optionFilterProp="props.question.state?.optionFilterProp || 'value'"
            @search="fetchUser"
            @popupScroll="handlePopupScroll"
            @change="(value, option) => selectQs({ key: props.question.key, value, option })"
            :open="isOpen"
            @dropdownVisibleChange="dropdownVisibleChange"
            :showArrow="true"
          >
            <template v-if="state.fetching" #notFoundContent>
              <a-spin size="small" />
            </template>
          </a-select>
        </template>
        <!-- 自动完成输入 -->
        <template v-else-if="props.question.type === 'auto'">
          <a-auto-complete
            v-model:value="props.question.value"
            :getPopupContainer="hangBody"
            :allowClear="props.question.state.allowClear === false ? false : true"
            :placeholder="props.question.placeholder || '请输入'"
            :disabled="props.question.disabled"
            style="width: 100%"
            :filter-option="false"
            :options="state.data"
            @search="fetchUser"
            @popupScroll="handlePopupScroll"
            @change="(value) => selectQs({ key: props.question.key, value })"
          >
          </a-auto-complete>
        </template>
        <template v-else-if="props.question.type === 'tree'">
          <a-tree-select
            v-model:value="props.question.value"
            :getPopupContainer="hangBody"
            @change="(value, label) => selectQs({ key: props.question.key, value, label })"
            :allowClear="props.question.state.allowClear === false ? false : true"
            show-search
            :show-checked-strategy="props.question.state.echoNodes ? (props.question.state.echoNodes === 'showAll' ? SHOW_ALL : SHOW_PARENT) : SHOW_CHILD"
            :multiple="props.question.state.multiple"
            :placement="props.question.state?.placement || 'bottomLeft'"
            :placeholder="props.question.placeholder || '请输入'"
            :tree-default-expand-all="props.question.state.expandAll || false"
            :tree-node-filter-prop="props.question.state.asChildren ? props.question.state.asChildren.title : fieldNames.title || 'label'"
            :fieldNames="props.question.state.asChildren ? props.question.state.asChildren : fieldNames"
            :load-data="props.question.state.loadData ? onLoadData : null"
            :disabled="props.question.disabled"
            :tree-data="props.question.options"
            :tree-node-label-prop="props.question.state.fullPath ? 'fullPath' : fieldNames.title"
            :tree-checkable="props.question.state.treeCheckable"
          />
        </template>
        <template v-else-if="props.question.type === 'tree-modal'">
          <TreeModal :question="props.question"></TreeModal>
        </template>
        <template v-else>
          <div>
            <a-select
              :mode="props.question.state.mode || ''"
              :getPopupContainer="hangBody"
              :fieldNames="props.question.state.asChildren ? props.question.state.asChildren : fieldNames"
              :showSearch="props.question.state?.showSearch"
              :allowClear="props.question.state.allowClear === false ? false : true"
              max-tag-count="responsive"
              :placement="props.question.state?.placement || 'bottomLeft'"
              :showArrow="true"
              :optionFilterProp="props.question.state?.optionFilterProp || 'value'"
              v-model:value="props.question.value"
              :placeholder="props.question.placeholder || '请输入'"
              :virtual="false"
              @popupScroll="handlePopupScroll"
              @change="(value, option) => selectQs({ key: props.question.key, value, option })"
              :disabled="props.question.disabled"
              :open="isOpen"
              @dropdownVisibleChange="dropdownVisibleChange"
            >
              <a-select-option v-for="item in props.question.options" :label="item.label" :key="item.value" :value="item.value">
                {{ item.label }}
              </a-select-option>
            </a-select>
          </div>
        </template>
      </template>
      <div v-if="props.question.state.describe" :style="{ color: props.question.state.describeColor ? props.question.state.describeColor : '#ccc' }">{{ props.question.state.describe }}</div>
    </a-form-item>
  </div>
</template>

<script setup lang="ts">
import { watch, getCurrentInstance, onMounted, onUnmounted, ref, reactive, computed, nextTick } from 'vue';
import { QuestionBase } from '../../../question-base';
import { filter } from 'rxjs/operators';
import { Subscription } from 'rxjs';
// import dictionary from '@/filters/dictionary';
import { INFOSERVE, INITSERVE, RESETVERIFY, SELECTSERVE } from '@/mixins/subject/subject-types';
import { formInfoStore } from '@/store/modules/form';
import { debounce } from 'lodash-es';
import { getDictionaryList } from '@/utils/dictionary';
import { addFullPath, assignParams, paramsData, showKeyName, treeFindById } from '@/components/public-template/publicMethod';
import localDictionary from '@/filters/dictionary';
import { findObjectByIdInArray, isHidden } from '@/utils';
import TreeModal from './tree-modal.vue';
import { TreeSelect } from 'ant-design-vue';

const SHOW_PARENT = TreeSelect.SHOW_PARENT;
const SHOW_CHILD = TreeSelect.SHOW_CHILD;
const SHOW_ALL = TreeSelect.SHOW_ALL;

const formStore = formInfoStore();
let dictionary = formStore.getDictionary;

//subject变量
let $subscribeSub: Subscription;

const { proxy }: any = getCurrentInstance();
let props = defineProps<{ question: QuestionBase<any>; formData: any; config?: any; dataForm?: any }>();
const emit = defineEmits(['update:formData', 'selectData']);
const state = reactive({
  data: [],
  fetching: false
});
let lastFetchId = 0;

const fieldNames: any = ref(
  props.question.state.fieldNames
    ? props.question.state.fieldNames
    : {
        children: props.question.state.nameChildren ? props.question.state.nameChildren : 'children',
        title: props.question.state.nameChildren ? props.question.state.nameKey : 'label',
        key: props.question.state.nameChildren ? props.question.state.nameValue : 'id'
      }
);

//分页参数
let pagination: any = reactive({
  pageNumber: 1,
  pageSize: 50
});

const hangBody = (e) => {
  if (props.config && props.config.style === 'table-form') {
    let idName =
      import.meta.env.VITE_PUBLIC_PATH.split('/')
        .find((res) => res.includes('-'))
        .split('-')[0] + 'Storage';
    return idName ? document.getElementById(idName) : document.body;
  } else {
    return e.parentNode.parentNode;
  }
};

watch(
  () => props.question.value,
  (val) => {
    state.fetching = false;
    emit('update:formData', val);
  },
  { flush: 'sync' }
);

onMounted(() => {
  subWatch();
  init();
});

//解绑
onUnmounted(() => {
  if ($subscribeSub != undefined) {
    $subscribeSub.unsubscribe();
  }
});

//静态数据
const staticView = computed(() => {
  if (props.question.value || props.question.value == 0) {
    if (Array.isArray(props.question.value)) {
      let names = props.question.options.filter((res) => props.question.value.includes(res.value));
      if (names && names.length) {
        return names.map((res) => res.label).join(',');
      }
    } else {
      let data = props.question.options.find((res) => res.value === props.question.value);
      if (data) {
        return data.label;
      } else {
        let str = '';
        const getLabel = (data, value) => {
          data?.map((item) => {
            if (item.value === value) {
              str = item.label;
            }
            if (item.children?.length > 0) {
              getLabel(item.children, value);
            }
          });
        };
        getLabel(props.question.options, props.question.value);
        return str;
      }
    }
  }
  return props.question.value;
});
//sdw显示label拼接参数
const joinLabel = (data) => {
  let str = '';
  if (props.question.state && props.question.state.joinLabel) {
    str = `${data[props.question.state.nameKey || fieldNames.value.title]}${props.question.state.joinSymbol || '#'}${data[props.question.state.joinLabel]}`;
  } else {
    str = data[props.question.state.nameKey || fieldNames.value.title];
  }
  return str;
};
//开启模糊搜索
const filterOption = (input, option) => {
  return option.label.toLowerCase().index0f(input.toLowerCase()) >= 0;
};

//搜索
const fetchUser = debounce((value: any = null) => {
  lastFetchId += 1;
  const fetchId = lastFetchId;
  state.fetching = true;
  let params = {};
  if (props.question.state.popupScroll) {
    params = Object.assign({}, pagination);
    pagination.pageNumber++;
  } else {
    state.data = [];
  }
  params = Object.assign(params, props.question.state.params || {});
  if (value && value !== 0) {
    params[props.question.state.nameKey || props.question.key] = value;
  }
  proxy.$Http.api(props.question.state.url, params, props.question.state.protType ? props.question.state.protType : 'get').then((res) => {
    if (res) {
      if (fetchId !== lastFetchId) {
        // for fetch callback order
        return;
      }
      let data = res?.data?.map((data: any) => ({
        label: joinLabel(data),
        value: data[props.question.state.nameValue],
        ...data
      }));
      if (props.question.state.popupScroll) {
        state.data.push(...data);
      } else {
        state.data = data;
      }
      props.question.options = state.data;
      state.fetching = false;
      loadingOptions.value = false;
    }
  });
}, 300);

//滚动自动分页
const loadingOptions = ref(false);
const handlePopupScroll = async (e) => {
  if (!props.question.state.popupScroll) {
    return;
  }
  if (e.target && e.target.scrollTop + e.target.clientHeight + 30 >= e.target.scrollHeight) {
    console.log('到底了');
    if (!loadingOptions.value) {
      loadingOptions.value = true;
      if (props.question.type === 'search' || props.question.type === 'auto') {
        fetchUser(props.question.value);
      } else {
        getOptions();
      }
    }
  }
};

//接口获取options
const getOptions = debounce((fn: any = null) => {
  let params = {};
  if (props.question.state.popupScroll) {
    params = Object.assign({}, pagination);
  }
  params = Object.assign(params, props.question.state.params || {}, props.question.state.assign || {});
  proxy.$Http.api(props.question.state.url, params, props.question.state.protType ? props.question.state.protType : 'get').then((res) => {
    if (res) {
      // // 递归children
      pagination.pageNumber++;
      let data = reData(res.data);
      if (props.question.state.popupScroll) {
        props.question.options.push(...data);
      } else {
        props.question.options = data;
      }
      addFullPath(props.question.options, fieldNames.value.children, fieldNames.value.title, '/');
      state.data = props.question.options;
      if (fn) {
        fn();
      }
    }
    loadingOptions.value = false;
  });
}, 300);

//动态加载
const onLoadData = (treeNode) => {
  return new Promise((resolve) => {
    if (treeNode.dataRef[fieldNames.value.children]) {
      resolve(true);
      return;
    }
    let params: any = Object.assign({}, props.question.state.loadData.assign || {}, assignParams(treeNode.dataRef, props.question.state.loadData));
    proxy.$Http.api(props.question.state.url, params, props.question.state.protType ? props.question.state.protType : 'get').then((res) => {
      if (res && res.data) {
        addFullPath(res.data, fieldNames.value.children, fieldNames.value.title, '/', treeNode.dataRef.fullPath);
        if (res.data.length) {
          treeNode.dataRef[fieldNames.value.children] = reData(res.data);
        } else {
          treeNode.dataRef.isLeaf = true;
        }
        props.question.options = [...props.question.options];
        resolve(true);
      }
    });
  });
};

function reData(list: any[]) {
  if (!list) {
    return [];
  }
  // 数组的元素为string时
  if (list.some((item) => typeof item == 'string')) {
    return list.map((data: any) => ({
      label: data,
      value: data
    }));
  }
  return list.map((data: any) => {
    const item: any = { ...data, label: joinLabel(data), value: data[props.question.state.nameValue || fieldNames.value.key] + '' };
    //条件判断是否禁用
    if (Array.isArray(props.question.state.disabled)) {
      item.disabled = isHidden(item, { showKey: props.question.state.disabled });
    }
    //判断是否异步加载
    if (props.question.state.loadData) {
      item.isLeaf = false;
    }
    //开启子集选择
    if (props.question.state.asChildren && props.question.state.asChildren.select) {
      item.disabled = true;
    }
    //处理项数据回调
    if (props.question.state.callback && typeof props.question.state.callback === 'function') {
      props.question.state.callback(item);
    }
    //子集变动
    if (props.question.state.asChildren && props.question.state.asChildren.children && data[props.question.state.asChildren.children]) {
      console.log('找到问题了', item);
      item[props.question.state.asChildren.children] = data[props.question.state.asChildren.children].map((cItem: any) => ({
        ...cItem,
        label: cItem[props.question.state.asChildren.title],
        value: cItem[props.question.state.asChildren.key]
      }));
    } else if (data[props.question.state.nameChildren || fieldNames.value.children] && data[props.question.state.nameChildren || fieldNames.value.children].length > 0) {
      item[props.question.state.nameChildren || fieldNames.value.children] = reData(data[props.question.state.nameChildren || fieldNames.value.children]);
    }
    return item;
  });
}

//动态加载end

const init = () => {
  if (props.question.type === 'search') {
    fetchUser();
  }
  //取配置信息
  if (props.question.type === 'dictionary') {
    if (props.question.state.url) {
      getDictionaryList(props.question.state, (res) => {
        props.question.options = res;
      });
      return;
    }
    let dicObj: any = dictionary[props.question.state.filterName] || localDictionary[props.question.state.filterName];
    let arr: any = [];
    for (const key in dicObj) {
      if (dicObj.hasOwnProperty(key)) {
        arr.push({
          label: dicObj[key],
          value: props.question.state.valueType === 'string' ? key + '' : +key
        });
      }
    }
    props.question.options = arr;
    selectAction();
  } else if (props.question.state.url && props.question.type !== 'search') {
    getOptions(() => {
      selectAction();
    });
  } else if (props.question.state.labelInValue && props.question.value) {
    props.question.value = props.question.value.map((res) => ({
      key: res[props.question.state.labelInValue.value],
      label: res[props.question.state.labelInValue.label],
      value: res[props.question.state.labelInValue.value]
    }));
    selectAction();
  } else {
    selectAction();
  }
};

//监听动态表单数据完成
const subWatch = () => {
  $subscribeSub = proxy.$NotificationFormSub
    .getParams()
    .pipe(filter((res: any) => res !== 0 && res.key !== RESETVERIFY))
    .subscribe((item: any) => {
      try {
        if (item.key === INFOSERVE) {
          //数据都全部都到了
          selectQs({ key: props.question.key, initState: true });
        }
        //联动同类型的初始化
        if (item.key == INITSERVE && item.value.initKeys.includes(props.question.key) && ((props.config.name && props.config.name === item.value.configName) || !props.config.name)) {
          init();
        }
      } catch (error) {}
    });
};

const selectQs = (obj: any = { key: '', initState: false }) => {
  console.log('选中了吗', props.question.value);
  let treeSelect = null;
  if (obj.label) {
    treeSelect = treeFindById(props.question.options, props.question.value, props.question.state.nameChildren);
    console.log('属性选中的数据', treeSelect);
  }
  if (props.question.value === null && (props.question.state.mode === 'tags' || props.question.state.mode === 'mult')) {
    props.question.value = [];
  }

  switch (obj.key) {
    default:
      proxy.$NotificationFormSub.pushParams({
        key: SELECTSERVE,
        value: {
          key: props.question.key,
          value: props.question.value,
          initState: obj.initState,
          data: state.data,
          name: props.question.state.name || ''
        }
      });
      break;
  }

  selectAction();

  //初始化服务
  if (!obj.initState && props.question.state.initKeys) {
    proxy.$NotificationFormSub.pushParams({
      key: INITSERVE,
      value: {
        initKeys: props.question.state.initKeys,
        isOptionReplace: props.question.state.isOptionReplace,
        name: props.question.state.name || '',
        configName: props.config.name || ''
      }
    });
  }
  console.log('选中的值', obj.value);

  if (props.question.state.labelInValue) {
    let arr = [];
    if (props.question.type === 'tree') {
      // let item = treeFindById(props.question.options, props.question.value, props.question.state.nameChildren);
      // if(item){
      //   arr = [item];
      // }
    } else if (props.question.state.mode === 'tags' || props.question.state.mode === 'multiple') {
      if (Array.isArray(props.question.value) && props.question.value.length) {
        let ids = props.question.value.map((res) => (typeof res === 'string' ? res : res[fieldNames.value.key]));
        arr = props.question.options.filter((res) => ids.includes(res.value));
        if (arr && arr.length) {
          props.question.value = arr.map((res) => ({
            key: res.key || res.value || res[props.question.state.labelInValue.value],
            [props.question.state.labelInValue.label]: res.label || res[props.question.state.labelInValue.label],
            [props.question.state.labelInValue.value]: res.value || res[props.question.state.labelInValue.value]
          }));
        } else {
          props.question.value = props.question.value.map((res) => ({
            key: typeof res === 'string' ? res : res.key || res.value || res[props.question.state.labelInValue.value],
            [props.question.state.labelInValue.label]: typeof res === 'string' ? res : res.label || res[props.question.state.labelInValue.label],
            [props.question.state.labelInValue.value]: typeof res === 'string' ? res : res.value || res[props.question.state.labelInValue.value]
          }));
        }
      }
    } else {
      arr = props.question.options.filter((res) => res.value === props.question.value);
      console.log('选中的数据', arr, props.question.options, props.question.value);
      if (arr && arr.length) {
        props.question.value = arr.map((res) => ({
          key: res.key || res.value || res[props.question.state.labelInValue.value],
          [props.question.state.labelInValue.label]: res.label || res[props.question.state.labelInValue.label],
          [props.question.state.labelInValue.value]: res.value || res[props.question.state.labelInValue.value]
        }));
      }
    }
  }

  emit('selectData', {
    key: props.question.key,
    value: props.question.value,
    initState: obj.initState,
    option: obj.label ? treeSelect : obj.option,
    name: props.question.state.name || ''
  });
  console.log('选中的值', props.question.value);
};
//选择灵动
const selectAction = () => {
  console.log('选择数据');
  //控制form参数
  if (props.question.state && props.question.state.changeOptions && !props.question.hidden) {
    updateOptions(props.question.state.changeOptions[props.question.value] || props.question.state.changeOptions['default']);
  }
  //自动灵动更新同级组件属性并初始化
  if (props.question.state.changeAuto && props.question.value !== null) {
    let data: any = {};
    if (props.question.type === 'tree') {
      data = findObjectByIdInArray(props.question.options, props.question.value, 'id', fieldNames.value.children);
    } else {
      data = props.question.options.find(
        (res) => res.value === (typeof props.question.value === 'string' || typeof props.question.value === 'number' ? props.question.value : props.question.value[0])
      );
    }
    let options = [];
    if (data && !props.question.state.offChangeAuto && props.question.value) {
      if (Array.isArray(props.question.state.changeAuto)) {
        props.question.state.changeAuto.forEach((item) => {
          options.push({
            key: item.key,
            option: item.option,
            isAssign: item.isAssign || false,
            value: item.isOptionReplace ? replaceOptions(data, item) : typeof item.value === 'string' ? showKeyName(data, item.value) : paramsData(data, { params: item.value }, props.question.value)
          });
        });
      } else {
        for (const key in props.question.state.changeAuto) {
          if (props.question.state.changeAuto[key]) {
            options.push({
              key,
              option: props.question.state.changeAuto[key]?.option || 'state.params',
              isAssign: props.question.state.changeAuto[key].isAssign || false,
              value:
                typeof props.question.state.changeAuto[key].value === 'string'
                  ? showKeyName(data, props.question.state.changeAuto[key].value)
                  : paramsData(data, { params: props.question.state.changeAuto[key].value }, props.question.value)
            });
          }
        }
      }
    }
    options.length && updateOptions(options);
    console.log('选中的值', options, data);
  }
  //选中后带上额外参数一起提交
  extendParams();
};

//sdw 替换options
const replaceOptions = (data, item) => {
  let obj = {};
  for (const key in item.value) {
    obj[key] = showKeyName(data, item.value[key]);
  }
  return [obj];
};

//更新云数据
const updateOptions = (arr: any = []) => {
  const formStore = formInfoStore();
  if (props.question.state.type === 'layer' || props.config.type === 'layer') {
    formStore.updateLayerQuestions(arr);
  }
  formStore.updateQuestions(arr);
  //动态改变表单
  proxy.$NotificationFormSub.pushParams({ key: RESETVERIFY, value: { name: 'form' } });
};

//扩展字段
const extendParams = () => {
  if (props.question.state.changeParams && props.question.value) {
    let data: any = {};
    if (props.question.type === 'tree') {
      data = findObjectByIdInArray(props.question.options, props.question.value, 'id', fieldNames.value.children);
    } else {
      data = props.question.options.find((res) => (typeof props.question.value === 'object' ? props.question.value.includes(res.value) : res.value === props.question.value));
    }
    let params = paramsData(data, { params: props.question.state.changeParams });
    props.question.state.extendParams = Object.assign({}, props.question.state.extendParams, params);
    console.log('看下参数', props.question.state);
  }
};
const isOpen = ref(false);
const dropdownVisibleChange = (open) => {
  isOpen.value = open;
  nextTick(() => {
    const selectDialogDom = document.querySelectorAll('.ant-select-dropdown') as any;
    selectDialogDom?.forEach?.((el: Element) => {
      el.addEventListener('mouseleave', () => {
        isOpen.value = false;
      });
    });
  });
};

// rc-virtual-list
</script>

<style lang="less" scoped>
@import url('./input-select.component.less');
</style>
